/***************************************************************************
 *  -- Copyright Bit Armory Labs 2007
 *
 * FILE:     NLinkWebProject.cs, 110 code lines, [3.20 KB]
 * DATE:     8/25/2007 11:35 PM
 * MODIFIED: 8/28/2007 11:36 AM
 * PATH:     C:\Programming\Projects\Slinks\Slinks.Resources
 *
 * NAMESPACE: Slinks.Generator
 * CLASS:     NLinkWebProject
 *
 * AUTHOR:   Brian Chavez (Cowboy), bchavez@bitarmory.com
 *
 *                        Licence
 *
 * This library, code generator, and source code
 * is licensed under the terms and conditions defined in the GNU Public
 * License. You are free to use it for non-commercial purposes.
 * If you are going to use any part of it in a commercial 
 * application, contact me and we can work something out.
 * You may use the code generated output of Slink and Slink
 * as a development tool in both commercial and 
 * non-commercial applications.
 *
 * THE SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS", WITHOUT WARRANTY
 * OF ANY KIND, EXPRESS OR IMPLIED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF THIS
 * SOFTWARE.
 ***************************************************************************/

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System;
using Slink.Core;
using TaHoGen.Targets;
using TaHoGen;
using System.Reflection;
using System.Diagnostics;
using System.Text;
using TaHoGen.Generators;
namespace Slink.Generator
{
    /// <summary>
    /// NLink web project
    /// </summary>
    public class SlinkManagedWebProject
    {
        public event EventHandler ProjectFilesChanged;
        
        private string onDiskHash;
        private string vsWebProjectFullFilePathOnDisk;
        private SlinkConfigFile configFile;
        private Dictionary<string, SlinkNamespace> namespaces;

        public SlinkManagedWebProject( string vsWebProject )
        {
            this.vsWebProjectFullFilePathOnDisk = vsWebProject;
            this.configFile = new SlinkConfigFile( this.VsWebProjectFullFilePathOnDisk );
            this.namespaces = new Dictionary<string, SlinkNamespace>();
        }

        /// <summary>
        /// Get aspx files
        /// </summary>
        public string[] GetAspxFiles()
        {
            return Directory.GetFiles( this.VsWebProjectFullFilePathOnDisk, "*.aspx", SearchOption.AllDirectories );
        }


        /// <summary>
        /// Is code synced
        /// </summary>
        /// <returns>Bool</returns>
        public bool IsCodeSynced
        {
            get
            {
                return this.GetNSolidLinkFileHash().Equals( this.GetInMemoryHash() );
            }
        }

        public SlinkConfigFile ConfigFile
        {
            get
            {
                return this.configFile;
            }
        }

        public string VsWebProjectFullFilePathOnDisk
        {
            get
            {
                return this.vsWebProjectFullFilePathOnDisk;
            }
        }

        /// <summary>
        /// Get on disk hash
        /// </summary>
        /// <returns>String</returns>
        private string GetNSolidLinkFileHash()
        {
            string nlinkFileLocation = Path.Combine( this.VsWebProjectFullFilePathOnDisk, this.ConfigFile.TypesafeGenerateFileTarget );
            if( !File.Exists( nlinkFileLocation ) )
            {
                return string.Empty;
            }
            else
            {
                string result = "";
                try
                {
                    using( StreamReader sr = new StreamReader( nlinkFileLocation ) )
                    {
                        string firstLine = sr.ReadLine();
                        if( string.IsNullOrEmpty( firstLine ) )
                        {
                            return string.Empty;
                        }
                        result = firstLine.Trim().Replace( "//", "" );
                    }
                }
                catch( Exception e )
                {
                    throw e;
                }
                return result;
            }
        }

        /// <summary>
        /// Get in memory hash
        /// </summary>
        /// <returns>String</returns>
        private string GetInMemoryHash()
        {
            return Utils.CalculateMD5( string.Join( ",", this.GetAspxFiles() ) );
        }

        public void GenerateTypesafetyFile()
        {
            this.namespaces.Clear();
            
            FileTarget targetOutput = new FileTarget( Path.Combine( this.VsWebProjectFullFilePathOnDisk, this.ConfigFile.TypesafeGenerateFileTarget ), FileMode.Create );

            foreach( NamespaceRulesElement rule in this.ConfigFile.NamespaceRules)
            {
                foreach( string file in Directory.GetFiles(this.VsWebProjectFullFilePathOnDisk,rule.Extension, SearchOption.AllDirectories))
                {
                    this.AddFileToNamespace( file, rule );
                }
            }
            
            //StreamWriter streamW = new StreamWriter()

            //SimpleTextGenerator header = new SimpleTextGenerator();
            //header.Text = "//hash=";
            
            foreach( SlinkNamespace slinkNamespace in this.namespaces.Values)
            {
                targetOutput.Attach( slinkNamespace.GetNamespaceTextGenerator() );
            }

            targetOutput.Write();
        }

        
        /// <summary>
        /// Add file to namespace
        /// </summary>
        /// <param name="file">File</param>
        private void AddFileToNamespace( string file, NamespaceRulesElement rule )
        {   
            string nsForFile = SlinkNamespace.GetNamespace( file, rule, this );

            SlinkNamespace slinksContainer;
            
            if( this.namespaces.ContainsKey( nsForFile ) )
            {
                slinksContainer = this.namespaces[nsForFile];
            }
            else
            {
                slinksContainer = new SlinkNamespace( nsForFile );
                this.namespaces.Add( nsForFile, slinksContainer );
            }

            SlinkClass slinkClass = new SlinkClass( this, rule, file );

            if( slinksContainer.SlinkClasses.ContainsKey( slinkClass.ClassName ) )
            {
                slinksContainer.SlinkClasses.Remove( slinkClass.ClassName );
            }
            
            slinksContainer.SlinkClasses.Add( slinkClass.ClassName, slinkClass );
        }


        ///// <summary>
        ///// Write n links file
        ///// </summary>
        //public void GenerateTypesafetyFile_OLD()
        //{
        //    FileTarget SlinksFile = new FileTarget( Path.Combine( this.vsWebProjectFilePath, this.configFile.TypesafeGenerateFileTarget ), FileMode.Create );
            
        //    foreach( string aspxFile in this.GetAspxFiles() )
        //    {
        //        //Compile the template assembly
        //        Assembly templateAssembly = TemplateCompiler.Compile( System.Text.ASCIIEncoding.ASCII.GetString( NSolidLink.Generator.Properties.Resources.ClassTemplate ) );
        //        if( templateAssembly == null )
        //        {
        //            throw new Exception( "Error creating template assembly." );
        //        }

        //        //Get the template type.
        //        Type templateType = templateAssembly.GetTypes()[0];

        //        if( templateType == null )
        //        {
        //            throw new Exception( "Error creating template type." );
        //        }

        //        //Set the properties for the template
        //        PropertyTable pt = new PropertyTable();
        //        pt["ClassNamespace"] = this.GetFolderNamespace( aspxFile );
        //        pt["ClassName"] = this.GetClassNameForAspxFile( aspxFile );
        //        pt["AbsoluteUrl"] = this.GetAbsoluteUrlForAspxFile( aspxFile );
        //        pt["TildeUrl"] = this.GetTidleUrlForAspxFile( aspxFile );

        //        //Instantiate the template and assign properties at the same time.
        //        object[] args = new object[] { pt };
        //        TextGenerator textGenterator = Activator.CreateInstance( templateType, args ) as TextGenerator;
                
        //        if( textGenterator == null )
        //        {
        //            throw new Exception( "Error creating  generator" );
        //        }
                
        //        SlinksFile.Attach( textGenterator );

        //        SlinksFile.Write();
        //    }
        //}

        
    }
}